AWS CDKのConstructをCDK for Terraformで使用できるAWS Adapterを使ってみた
「CDKTFでAWS Adapterを使えばAWS CDKのConstructを使用できる!?」
CDKTFのドキュメントを見ていたら、AWS Adapter というものを見つけました。(2022/8現在は、technical previewです)
»[technical preview] AWS Adapter
CDKTFはTerraformをラップするだけではなく、AWS Adapterを使うことでAWS CDKのConstructを使用できるようです。
ざっくり紹介と試した内容をブログにします。
AWS Adapterとは
通常CDKTFでAWSリソース作成する際は、AWSプロパイダ(hashicorp/cdktf-provider-aws)を使用します。
AWS Adapterを使用することで、AWS CDKのライブラリ(aws/aws-cdk)を使用することができます。
見てもらった方が理解しやすいかと思うので、公式ドキュメントのコードを引用します。
import { Duration, aws_lambda, aws_events, aws_events_targets, } from "aws-cdk-lib"; import { AwsTerraformAdapter, AwsProvider } from "@cdktf/aws-cdk"; export class MyStack extends TerraformStack { constructor(scope: Construct, name: string) { super(scope, name); new AwsProvider(this, "aws", { region: "us-west-2" }); const awsAdapter = new AwsTerraformAdapter(this, "adapter"); // aws-cdkでリソース作成 // scopeの部分にはawsAdapterを入れる const lambdaFn = new aws_lambda.Function(awsAdapter, "lambda", { code: new aws_lambda.InlineCode( `def main(event, context): print("I'm running!")` ), handler: "index.main", timeout: Duration.seconds(300), runtime: aws_lambda.Runtime.PYTHON_3_6, }); const rule = new aws_events.Rule(awsAdapter, "rule", { schedule: aws_events.Schedule.expression("cron(0 18 ? * MON-FRI *)"), }); rule.addTarget(new aws_events_targets.LambdaFunction(lambdaFn)); } }
CDKTFでAWS CDKを使えると、L2 L3 ConstructやConstruHubのCDKライブラリを使ってより簡単にインフラ定義ができるというメリットがあると思います。
AwsTerraformAdapterはAWS Cloud Control API 使用しています。 その関係で、AWS Cloud Control APIが対応していないリソースに関しては使用するにあたりloudFormationとTerraformの手動Mapping必要です。
Mappingの定義方法についても、上記ドキュメント上で紹介されていました。 気になる方は、そちらをご参照ください。
やってみた
CDKTFでAWS CDKのL2Constructを使ってVPC作成
CDKTF用のファイルを用意します。
$ npx cdktf init --template=typescript --local
その後、AWS CDKを使用するために必要なパッケージをインストールします。
$ npm install aws-cdk-lib @cdktf/aws-cdk
以下のファイルを用意します。
import { Construct } from "constructs"; import { App, TerraformStack, TerraformOutput } from "cdktf"; import * as ec2 from 'aws-cdk-lib/aws-ec2'; import { AwsTerraformAdapter, AwsProvider } from "@cdktf/aws-cdk"; export class VpcStack extends TerraformStack { constructor(scope: Construct, name: string) { super(scope, name); new AwsProvider(this, "aws", { region: "ap-northeast-1" }); const awsAdapter = new AwsTerraformAdapter(this, "adapter"); new ec2.Vpc(awsAdapter, 'VPC', { cidr: "10.0.0.0/16", natGateways: 0, subnetConfiguration: [ { cidrMask: 24, name: 'public', subnetType: ec2.SubnetType.PUBLIC, }, ] }); } } const app = new App(); new VpcStack(app, "vpc", ); app.synth();
コマンドでスタックやリソースの状態を確認します。
diffの結果は抜粋しています。
diffを見たところ、L2 Constructを使用しているためVPC以外にもSubnetやRouteTable、IGWなど関連リソースを作成してくれているのがわかります。
$ npx cdktf list # スタックの確認 Stack name Path vpc cdktf.out/stacks/vpc $ npx cdktf diff # 作成されるリソースの確認 ### 抜粋 ### vpc # aws_subnet.vpc_adapter_VPCpublicSubnet2Subnet2B2DFF71_3903EC71 (adapter/VPCpublicSubnet2Subnet2B2DFF71) will be created + resource "aws_subnet" "vpc_adapter_VPCpublicSubnet2Subnet2B2DFF71_3903EC71" { + arn = (known after apply) + assign_ipv6_address_on_creation = false + availability_zone = "ap-northeast-1c" + availability_zone_id = (known after apply) + cidr_block = "10.0.1.0/24" + enable_dns64 = false + enable_resource_name_dns_a_record_on_launch = false + enable_resource_name_dns_aaaa_record_on_launch = false + id = (known after apply) + ipv6_cidr_block_association_id = (known after apply) + ipv6_native = false + map_public_ip_on_launch = true + owner_id = (known after apply) + private_dns_hostname_type_on_launch = (known after apply) + tags_all = (known after apply) + vpc_id = (known after apply) } # aws_vpc.vpc_adapter_VPCB9E5F0B4_256A8F5A (adapter/VPCB9E5F0B4) will be created + resource "aws_vpc" "vpc_adapter_VPCB9E5F0B4_256A8F5A" { + arn = (known after apply) + cidr_block = "10.0.0.0/16" + default_network_acl_id = (known after apply) + default_route_table_id = (known after apply) + default_security_group_id = (known after apply) + dhcp_options_id = (known after apply) + enable_classiclink = (known after apply) + enable_classiclink_dns_support = (known after apply) + enable_dns_hostnames = true + enable_dns_support = true + id = (known after apply) + instance_tenancy = "default" + ipv6_association_id = (known after apply) + ipv6_cidr_block = (known after apply) + ipv6_cidr_block_network_border_group = (known after apply) + main_route_table_id = (known after apply) + owner_id = (known after apply) + tags_all = (known after apply) } Plan: 10 to add, 0 to change, 0 to destroy. ───────────────────────────────────────────────────────────────────────────── Saved the plan to: plan To perform exactly these actions, run the following command to apply: terraform apply "plan"
deployで実際にリソース作成します。
$ npx cdktf deploy
マネジメントコンソールからもリソース作成が確認できました。
検証が終わったらdestroyでリソース削除します。
$npx cdktf destroy
おわりに
AWS CDKのConstructが使えるのはかなり便利なのでAWS AdpterのGAが待ち遠しいです。
小ネタなんですが、cdktfのコマンド deployにはapplyが、diffにはplanがそれぞれエイリアスとして設定されていました。
(cdktf deployと打とうとしたところ、Terraformの癖でcdktf applyと打っても動いたのて気づきました)
Terraformに慣れている方には、嬉しいですね。
$ npx cdktf help cdktf コマンド: cdktf init Create a new cdktf project from a template. cdktf get Generate CDK Constructs for Terraform providers and modules. cdktf convert Converts a single file of HCL configuration to CDK for Terraform. Takes the file to be converted on stdin. cdktf deploy [stacks...] Deploy the given stacks [エイリアス: apply] cdktf destroy [stacks..] Destroy the given stacks cdktf diff [stack] Perform a diff (terraform plan) for the given stack [エイリアス: plan]